avashe CleanArchitecture本勉強ログ
1章、ソフトウェアアーキテクチャの重要性を説明する回
ソフトウェアアーキテクチャの目的とはシステムの構築および保守に必要な人材を最小限に抑えること
ケーススタディとして匿名希望の企業の実データを参照している
エンジニアの雇用人数は指数関数的に増大している一方、メジャーリリースごとのコード行数は対数的にスケールしている。つまりコスト(エンジニア全体に支払う給料)が青天井なのに対しソフトウェアの規模は頭打ちになってしまっている。
コードが汚くても今リリースしよう→直されることはない
競争相手が常にいるため常に新機能開発に時間が割かれることになる
崩壊したコードを書くよりもクリーンなコードを書く方が常に遅い
ただし、この下りは個人のソフトウェアエンジニアの実験を参照しており、信頼性には欠ける
2章、二つの価値
ソフトウェアの1つめの価値は振る舞い、2つめの価値は柔軟性(ソフトであること)
変更の難易度は変更の形状ではなく、変更のスコープに比例しなければならない
avashe.iconここでの議論は抽象的だが、形状とは具体的な実装によって生まれる制約のこと、だと私には読める。
ここで「形状」という聞き慣れない言葉を使っているが、私は比喩としては適切だと考えている。ソフトウェア開発者は、「四角い」ペグを「丸い」穴に打ち込まなければいけないような 気持ちになることがよくある。 この問題はもちろん、システムのアーキテクチャの問題である。アーキテクチャが特定の「形状」を選択していると、新しい機能がその構造に適さない可能性が高くなっていく。したがっ て、形状にとらわれないアーキテクチャにしたほうが実用的である (p.42)
avashe.icon 形状に囚われないアーキテクチャとは~というのが本書の内容になっていくことがわかる。直感的にはインターフェースが要件に対して適切な粒度で整理されたソフトウェアがそれにあたると思う。
ソフトウェアが動作することと簡単に変更できることどちらが重要か?基本的には動作することが大事だというがこれは間違った態度である。それは以下を比べてみればわかる。
完璧に動作するが変更できないソフトウェアが与えられたとき、それはいずれ要件が変更されたタイミングで役に立たなくなる
現実においても変更のコストがメリットを上回ったことで実質的に変更不能になったプロダクトは散見される
動作しないが変更が簡単なプログラムが与えられたとき、それは多少のコストで修正でき、要件が変更されても引き続き修正して使うことができる
ソフトウェアエンジニアは機能の緊急性よりもアーキテクチャの重要度を強く擁護しなければならない
著者はアーキテクチャは「重要だが常に緊急とは限らない」コードの振る舞いは「緊急だが常に重要とは限らない」とする
ビジネスマネージャはしばしば「緊急だが重要ではない」ものと「緊急かつ重要」なものを区別できていないため、アーキテクチャを過小評価し、ふるまいが動作することを過大評価している
ソフトウェアエンジニアはビジネスマネージャの代わりにアーキテクチャの重要性を主張していく必要がある
アーキテクチャが汚いのはソフトウェアエンジニアがその権利主張の場において戦わなかったことを示している、戦うことこそがあなたが雇用された責任を果たすことでもある
3章、プログラミングパラダイムについて
構造型、オブジェクト指向、関数型の三つがある
なぜ本書においてこの三つだけに着目しているかというと、プログラマから能力を削除しているものがこれらだから
3つのパラダイムはそれぞれ、完全なgoto文、関数ポインタ、代入(Mutability)を奪っていることが重要である
avashe.iconあまりにも現代プログラミングの前提すぎてわかってなかったけど、無秩序なgoto文からif/then/elseやdo/whileなどの制御構造を抽出し、制限した時点で構造化は達成されているのか
あらゆるプログラムが順次・選択・反復の構造で構築できることを発見したのはBohmとJacopiniで(構造化定理)、これを知っていたDijkstraがプログラミング言語に落とし込んだ ただしDijkstra自身はプログラムのバグがないことを数学的に証明するような言語を構想しており、本書曰くその方向性では成功しなかったと言っている
数学的方法と科学的方法の違いが比較される
プログラムの正しさを検証する戦略として数学的証明があるが、これは現状大きい成功を収めていない、もう一方科学的方法がある
科学の理論や法則は証明可能性ではなく、反証可能性の世界である
ニュートンの運動の第二法則(F = ma)は実証することはできるが、どれだけ実証的な証拠を集めても将来反証できる可能性が残されている
科学は真であることを証明するのではなく、多くの労力をかけても反証できない理論を目的のために十分真であるとみなす学問である
数学は証明可能な主張を真であると証明する学問であり、科学は証明可能な主張を偽であると証明する学問であると言えるだろう (p.57)
本書ではプログラミングもまた科学的方法が行われているとする
プログラミングのテストはそのプログラムが正しくないことは証明できるが、プログラムが正しいことは証明できない、つまりテストは反証するための仕組みである バグがある=プログラムが正しくないだが、バグがテストで見つからなかった=プログラムが正しいとはならない、テストで見つからないバグが残っているかもしれない
むしろソフトウェア開発は科学のようなものである。どれだけ最善を尽くしても正しくないことを証明できないとによって、その正しさを明らかにしているのである。(p.57)
自由にgotoできるプログラミング言語を前提に幾らモジュールをテストしても、実証的な証拠は積みあがらない
avashe.icon制約のある構造を持ち込むことの重要性がここで再度強調されている
アーキテクチャにおける機能分割がベストプラクティスなのはこれまで話してきた構造化プログラミングの教訓からも裏付けられる
ソフトウェアを反証しやすいように枠を規定しなければならず、そのためソフトウェアアーキテクトは複数の小さなコンポーネントに機能を分割しようとする
コンポーネントを組み合わせるレベルにおいても制約が必要だが、これについては後の章で述べる
5章、オブジェクト指向プログラミング
カプセル化、継承、ポリモーフィズムがOOの構成要素だという主張が多いので順にみていく
氏曰く、カプセル化はむしろC言語時代は完ぺきだったのにOO言語では弱まっている
C言語の時代は構造体のインスタンスのサイズを知る必要がなかったので、ヘッダファイルに構造体名だけを宣言しておき、実装にのみメンバ変数を宣言することでユーザには構造体の中身を知らせない完璧なカプセル化が実装できた
ユーザは提供されたライブラリのヘッダファイルを読み込むだけである
むしろC++コンパイラはクラスのインスタンスのサイズを知る必要があるためにヘッダファイルにメンバ変数を宣言する必要が生まれ、ユーザから見えるようになった
JavaやC#ではヘッダと実装の分離を廃止したのでさらに見えるようになった
avashe.iconカプセル化をアクセス権というだけではなくユーザであるプログラマに対する可視性まで拡張して批判しているのはやや論点ずらしな感はあるが、まぁC言語でも全然カプセル化はできるしやってたよね、というので十分な反証である
継承もアップキャストという形でC言語で実装されてきたテクニックにすぎない、ただし利便性は向上しているし、多重継承なども含めるとアップキャストでできなかったことが実装できている
ポリモーフィズムもC言語の時点で存在する関数ポインタを利用したテクニックであるが、危険である関数ポインタをプログラマから隠蔽して安全なものとした、これはOOの発明である
たとえばUNIXではすべてのIOドライバに対して5つの標準機能, open, close, read, write, seekの実装を求めており、これら関数のシグネチャも指定されている。そしてファイルを表現する構造体はそれら関数へのポインタである。こうすればIOドライバの実装の違いを隠蔽しながらファイルの読み書きを操作することができる。
ここで重要なのは関数ポインタが危険で、様々なバグの温床であったこと
例えばC++では仮想関数のポインタをvtableというデータ構造で持つことで自動的に管理してくれる